package com.example.spring5.AOP.AOP操作;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

public class AOP操作_基于AspectJ注解 {
    static ApplicationContext context = new ClassPathXmlApplicationContext("AOP.xml");

    public static void main(String[] args) {
        /**
         * 1.被增强类
         * 2.增强类(增强的代码)
         * 3.进行通知配置
         *      1.开启注解扫描  (需要xml增加名称空间 context 注解扫描 扫描路径)
         *      2.使用注解创建关于增强的方法 (需要xml增加名称空间 aop )
         *      3.加上@Component注解  增强类额外添加
         * 4、配置不同类型的通知
         *   （1）在增强类的里面，在作为通知方法上面添加通知类型注解，使用切入点表达式配置
         * 5. 相同切入点抽取
         * 6.有多个增强类多同一个方法进行增强，设置增强类优先级
         *      @ Order(1)//如果有多个增强类  设置优先级  越小优先级越高
         *
         */
        context.getBean("aspectJ_主",AspectJ_主.class).getA();

    }
}
@Component //默认名字是第一个字母变小写
class AspectJ_主{
    public void getA(){
//        int i=1/0;
        System.out.println("主方法");
    }
}
@Component
@Aspect //在xml中配置   只要找到这个类 会自动生成代理对象
//@Order(1)//如果有多个增强类  设置优先级  越小优先级越高  先执行
class AspectJ_副{

    //相同切入点抽取
    @Pointcut("execution(* com.example.spring5.AOP.AOP操作.AspectJ_主.getA())")
    public void pointDemo(){

    }

    //前置通知
    //@Before 注解表示作为前置通知
    @Order(1)
    @Before("pointDemo()")
    public void Before(){//只有环绕通知可以在他前面
        System.out.println("增强的方法之_______前置通知 优先级1");
    }

    @Order(2)
    @Before("pointDemo()")
    public void Before1(){//只有环绕通知可以在他前面
        System.out.println("增强的方法之_______前置通知 优先级2");
    }

    @AfterReturning("pointDemo()")
    public void AfterReturning(){//主方法一执行完就执行
        System.out.println("增强的方法之_______后置通知");
    }

    @After("pointDemo()")
    public void After(){ //finally  必定执行 而且一定在方法执行完  只有环绕通知可以在他后面
        System.out.println("增强的方法之_______最终通知");
    }

    @AfterThrowing("pointDemo()")
    public void AfterThrowing(){ //发生异常时执行
        System.out.println("增强的方法之_______异常通知");
    }

    @Around("pointDemo()") // 所以说此方法必定   在第一行 或者  最后一行(或者异常不执行)
    public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("增强的方法之_______环绕通知前");
        proceedingJoinPoint.proceed();//主方法(包括给他增强的方法)
        System.out.println("增强的方法之_______环绕通知后");
    }

}
